package com.colorlight.cloud.auth.util;

import com.colorlight.cloud.common.constants.CommonConstants;
import com.colorlight.cloud.common.exception.ParameterException;
import com.colorlight.cloud.common.utils.HexUtil;
import lombok.NonNull;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

import static com.colorlight.cloud.auth.model.AuthExceptionEnum.AUTH_PARAMETER_EXCEPTION;
import static com.colorlight.cloud.auth.model.AuthExceptionEnum.HMAC_SIGN_CALCULATION_EXCEPTION;

/**
 * @author Demon
 * 默认得三元组 转 id  密码 name
 */
public class ConnectUtil {
	/**
	 * {envPrefix}-{productKey}_{DeviceName}
	 * 三元组生成设备登陆name
	 *
	 * @param envPrefix  平台标识符
	 * @param productKey 烧录信息 密钥
	 * @param deviceName 烧录信息 烧录信息
	 * @return 三元组生成设备登陆name
	 * @author Demon
	 **/
	public static String getDeviceName(String envPrefix, String productKey, String deviceName) {
		
		if (stingIsEmpty(envPrefix)
				&& stingIsEmpty(productKey)
				&& stingIsEmpty(deviceName)) {
			return envPrefix +
					CommonConstants.CONNECTOR4 +
					productKey +
					CommonConstants.CONNECTOR5 +
					deviceName;
		}
		throw new ParameterException(AUTH_PARAMETER_EXCEPTION);
	}
	
	/**
	 *  {DeviceName}|securemode=3,signmethod=hmacsha1,timestamp={Timestamp}|
	 * @param deviceName 烧录信息 deviceName
	 * @param timeStamp  烧录信息 timeStamp
	 * @return 生成：getClientID
	 * @author Demon
	 * @date 2022/4/14/17:46
	 **/
	public static String getClientId(String deviceName, String timeStamp) {
		if (stingIsEmpty(deviceName) && stingIsEmpty(timeStamp)) {
			return deviceName +
					CommonConstants.CONNECTOR1 +
					CommonConstants.SECURE_MODE +
					CommonConstants.CONNECTOR2 +
					CommonConstants.SECURE_MODE_VALUE +
					CommonConstants.CONNECTOR3 +
					CommonConstants.SIGN_METHOD +
					CommonConstants.CONNECTOR2 +
					CommonConstants.HMAC_SHA1_ALGORITHM +
					CommonConstants.CONNECTOR3 +
					CommonConstants.TIMESTAMP +
					CommonConstants.CONNECTOR2 +
					timeStamp +
					CommonConstants.CONNECTOR1;
		}
		throw new ParameterException(AUTH_PARAMETER_EXCEPTION);
	}
	
	
	/**
	 * clientId{device}deviceName{productKey}_{device}productKey{envPrefix}timestamp{Timestamp}
	 * @param deviceName 烧录信息  名字
	 * @param productKey 烧录信息 产品名称
	 * @param timeStamp  实时信息 时间戳（s）
	 * @param envPrefix  平台前缀
	 * @return 密码明文
	 * @author Demon
	 **/
	public static String getPassword(String deviceName,
									 String productKey,
									 String timeStamp,
									 String envPrefix) {
		
		if (stingIsEmpty(deviceName)
				&& stingIsEmpty(productKey)
				&& stingIsEmpty(timeStamp)
				&& stingIsEmpty(envPrefix)) {
			return CommonConstants.CLIENT_ID +
					deviceName +
					CommonConstants.DEVICE_NAME +
					productKey +
					CommonConstants.CONNECTOR5 +
					deviceName +
					CommonConstants.PRODUCT_KEY +
					envPrefix +
					CommonConstants.TIMESTAMP +
					timeStamp;
			
		}
		throw new ParameterException(AUTH_PARAMETER_EXCEPTION);
	}
	
	
	/**
	 * @param content 校验信息 clientID
	 * @param key     校验信息 deviceSecret
	 * @return 根据信息计算密码
	 * @author Demon
	 * HmacSHA1 加密 UTF_8编码
	 **/
	public static String getHmacSign(String content, String key) {
		try {
			SecretKeySpec signKey = new SecretKeySpec(key.getBytes(), CommonConstants.HMAC_SHA1_ALGORITHM);
			Mac mac = Mac.getInstance(CommonConstants.HMAC_SHA1_ALGORITHM);
			mac.init(signKey);
			byte[] rawHmac;
			rawHmac = mac.doFinal(content.getBytes(StandardCharsets.UTF_8.toString()));
			return HexUtil.toHex(rawHmac);
		} catch (NoSuchAlgorithmException | InvalidKeyException | IllegalStateException | UnsupportedEncodingException e) {
			throw new ParameterException(HMAC_SIGN_CALCULATION_EXCEPTION);
		}
	}
	
	

	
	
	/**
	 *
	 * @param clientId 连接id
	 * @param userName
	 * @author Demon
	 * @date 1/2/2024/上午11:00
	 * @return
	 **/
	public static Map<String, String> parseConnectionDetail(@NonNull String clientId, @NonNull String userName) {

		Map<String, String> map = new HashMap<>(3);
		try {
			String[] split = clientId.split("\\|");
			String currentDeviceName = split[0];
			map.put(CommonConstants.DEVICE_NAME, currentDeviceName);
			String[] split1 = split[1].split("=");
			map.put(CommonConstants.TIMESTAMP,split1[3]);

			String[] split2 = userName.split("_");
			map.put(CommonConstants.PRODUCT_KEY,split2[0].split("-")[1]);

			if (!currentDeviceName.equals(split2[1])) {
				throw new ParameterException("invalid param");
			}
		} catch (ArrayIndexOutOfBoundsException e) {
			throw new ParameterException("invalid param");
		}
		return map;
	}
	
	private static boolean stingIsEmpty(CharSequence cs) {
		return cs != null && cs.length() != 0;
	}
}
